<template>
  <div>
    <canvas id="renderCanvas"></canvas>
  </div>
</template>

<script setup>
import {onMounted, onUnmounted} from 'vue';
import * as BABYLON from '@babylonjs/core';
import '@babylonjs/loaders/glTF'; // 引入 GLTF 加载器
import '@babylonjs/core/Debug/debugLayer';

let scene, canvas, engine, camera, light,lines,clonedTrain,shadowGenerator,junyunpoints,junyunfx
import '@babylonjs/inspector';
import {GridMaterial} from "@babylonjs/materials";
// ... YOUR SCENE CREATION

let controlPoints = [];

async function loadPointsJson() {
  const response = await fetch('/gudao.json');
  if (!response.ok) {
    throw new Error(`HTTP error! Status: ${response.status}`);
  }
  return response.json();
};
let data,points;

// 创建贝塞尔曲线函数（优化实现）
function createBezierCurve(splineData) {

  const controlPoints = splineData.splines[0].map(point => {
    const position = convertC4DToBabylon(point.co);
    const leftHandle = convertC4DToBabylon(point.handle_left);
    const rightHandle = convertC4DToBabylon(point.handle_right);
    return { position, leftHandle, rightHandle };
  });


  // 4. 生成贝塞尔曲线
  points = [];
  for (let i = 0; i < controlPoints.length - 1; i++) {
    const p0 = controlPoints[i].position;
    const p1 = controlPoints[i].rightHandle;
    const p2 = controlPoints[i+1].leftHandle;
    const p3 = controlPoints[i+1].position;

    const bezierCurve = BABYLON.Curve3.CreateCubicBezier(p0, p1, p2, p3, splineData.resolution_u);
    points.push(...bezierCurve.getPoints());
  }

  lines = BABYLON.MeshBuilder.CreateLines("curve", { points: points }, scene);

  // lines.scaling=new BABYLON.Vector3(0.02, 0.02, 0.02);

  // lines.position.y+=5



}



// c4d渲染
// 存储创建的对象
let tangentLines = [];
let curveMesh = null;
function bezierPoint(p0, p1, p2, p3, t) {
  const u = 1 - t;
  const tt = t * t;
  const uu = u * u;
  const uuu = uu * u;
  const ttt = tt * t;

  // 贝塞尔公式: B(t) = u³P₀ + 3u²tP₁ + 3ut²P₂ + t³P₃
  const x = uuu * p0.x + 3 * uu * t * p1.x + 3 * u * tt * p2.x + ttt * p3.x;
  const y = uuu * p0.y + 3 * uu * t * p1.y + 3 * u * tt * p2.y + ttt * p3.y;
  const z = uuu * p0.z + 3 * uu * t * p1.z + 3 * u * tt * p2.z + ttt * p3.z;

  return new BABYLON.Vector3(x, y, z);
}

function renderSpline() {
  // 清除旧对象
  if (controlPoints) controlPoints.forEach(point => point.dispose());
  if (tangentLines) tangentLines.forEach(line => line.dispose());
  if (curveMesh) curveMesh.dispose();

  controlPoints = [];
  tangentLines = [];
    // 创建曲线点
    const curvePoints = [];
    const segments = data.segments || [{start: 0, count: data.points.length}];

    segments.forEach(segment => {
      const start = segment.start;
      const count = segment.count;

      // 至少需要3个点才能形成贝塞尔曲线
      if (count < 3) return;

      // 为每个分段创建曲线
      for (let i = start; i < start + count - 1; i++) {
        if (i + 1 >= data.points.length) break;

        const p0 = new BABYLON.Vector3(
            data.points[i].position.x,
            data.points[i].position.y,
            data.points[i].position.z
        );

        const p1 = new BABYLON.Vector3(
            data.points[i].position.x + data.points[i].tangent_right.x,
            data.points[i].position.y + data.points[i].tangent_right.y,
            data.points[i].position.z + data.points[i].tangent_right.z
        );

        const p2 = new BABYLON.Vector3(
            data.points[i+1].position.x + data.points[i+1].tangent_left.x,
            data.points[i+1].position.y + data.points[i+1].tangent_left.y,
            data.points[i+1].position.z + data.points[i+1].tangent_left.z
        );

        const p3 = new BABYLON.Vector3(
            data.points[i+1].position.x,
            data.points[i+1].position.y,
            data.points[i+1].position.z
        );

        // 使用4阶贝塞尔曲线计算点
        const numPoints = 20; // 每段曲线的点数
        for (let j = 0; j <= numPoints; j++) {
          const t = j / numPoints;
          const point = bezierPoint(p0, p1, p2, p3, t);
          curvePoints.push(point);
        }
      }
    });

    // 创建曲线网格
    if (curvePoints.length > 1) {
      curveMesh = BABYLON.MeshBuilder.CreateLines("curve", {
        points: curvePoints,
        updatable: false,
        colors: Array(curvePoints.length).fill(new BABYLON.Color4(1, 1, 1, 1))
      }, scene);
    }

}

async function  jiazaiJson  (){


  data = await loadPointsJson();
  // createBezierCurve(data);
  renderSpline()
}

function convertC4DToBabylon(coords) {
  return new BABYLON.Vector3(coords[0], coords[1], coords[2]); // 正确转换公式
}``


async function path3D(totalPoints = 15) {

  await jiazaiJson()

  console.log("points",points)


  // 均匀的点
  const path = new BABYLON.Path3D(points);
  path.update(true);
  junyunpoints =[];
  junyunfx=[];

  for (let i = 0; i < totalPoints; i++) {
    const t = i / (totalPoints - 1);
    const point = path.getPointAt(t);
    junyunpoints.push(point);

    const tangent = path.getTangentAt(t);
    junyunfx.push(tangent);
  }


}

function addlight() {
  light = new BABYLON.DirectionalLight("myDirectionalLight", new BABYLON.Vector3(-0.22545859333668974, -0.6889007267707885, -0.6889007267707885), scene);
  light.intensity = 8
  light.position = new BABYLON.Vector3(45.7000617980957, 25.100811004638672, 25.100811004638672);// (debugNode as BABYLON.DirectionalLight)
}

function xiangji() {
  camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 1, BABYLON.Vector3.Zero(), scene);
  camera.attachControl(canvas, true);
  //可选：设置相机碰撞检测，避免相机穿过物体
  camera.checkCollisions = true;
  scene.collisionsEnabled = true;
  camera.collisionRadius = new BABYLON.Vector3(0.5, 0.5, 0.5);
}

function xiangji2() {
  // 创建自由相机（替代 ArcRotateCamera）
  const camera = new BABYLON.FreeCamera("camera", new BABYLON.Vector3(0, 1, -5), scene);
  camera.attachControl(canvas, true);
  // 设置相机移动速度和灵敏度
  camera.speed = 0.2;          // 移动速度
  camera.angularSensibility = 4000;  // 旋转灵敏度

// 限制相机高度范围（可选）
  camera.minZ = 0.1;           // 最小深度
  camera.maxZ = 1000;          // 最大深度
}

async function chebyQxzou() {

  //创建车模型
  const trainModelGroup = await createXADTrainModel(scene);
  let meshByName1 = scene.getMeshByName('GModel');
  let meshByName2 = scene.getMeshByName('PModel');
  let meshByName3 = scene.getMeshByName('NModel');


  // let xian2 = scene.getMeshByName('线1-1');


  let model=[meshByName1,meshByName2,meshByName3]



  console.log("points",junyunpoints)
  console.log("tangents",junyunfx)



  for (let i = 0; i < junyunpoints.length; i++) {

    let target = junyunfx[i].normalize();
    const tangentLine = BABYLON.MeshBuilder.CreateLines(`tangent_${i}`, {
      points: [
        junyunpoints[i],
        junyunpoints[i].add(target.scale(0.2))
      ]
    }, scene);
    tangentLine.color = new BABYLON.Color3(1, 1, 0);


    let number = i%3;
    clonedTrain =model[number].clone(`clonedTrain_`+i);

    setVisible(clonedTrain, true);
    clonedTrain.position=junyunpoints[i]
    clonedTrain.scaling.scaleInPlace(0.5);
    //四元数
    // 方法1：使用四元数直接设置朝向（推荐）
    // 计算从火车头初始朝向（X轴）到切线方向的旋转四元数
    let initialForward = new BABYLON.Vector3(1, 0, 0); // 火车头初始朝向是X轴
    let targetDirection = junyunfx[i].normalize();

    // 计算旋转轴和角度
    let rotationAxis = BABYLON.Vector3.Cross(initialForward, targetDirection);
    let rotationAngle = Math.acos(BABYLON.Vector3.Dot(initialForward, targetDirection));

    // 创建旋转四元数
    let rotationQuaternion = BABYLON.Quaternion.RotationAxis(rotationAxis, rotationAngle);

// // 添加绕Y轴旋转180度
//     const yRotation = BABYLON.Quaternion.RotationAxis(BABYLON.Vector3.Up(), Math.PI);
//     rotationQuaternion.multiplyInPlace(yRotation);
    clonedTrain.rotationQuaternion = rotationQuaternion;

  }



}

async function jiazaicj  () {

  const { meshes } = await BABYLON.SceneLoader.ImportMeshAsync(
      null,          // 导入所有网格（不传特定网格名称）
      "",            // 模型路径（留空表示当前路径）
      "scene_xad.glb",    // 模型文件名
      scene
  );
  // 整体缩放模型（调整根节点的缩放）
  const rootNode = meshes[0]; // 通常第一个网格是根节点
  // rootNode.scaling.scaleInPlace(0.01);

  const xianMeshes = scene.meshes.filter(mesh =>
      mesh.name.includes('线2-')
  );


  let points = []

  for (let i = 0; i < xianMeshes.length; i++) {

    let position = xianMeshes[i].position;
    // position.x=-position.x
    // position.z=-position.z

    points.push(position)
  }

  console.log("xian2", points)

  return points
}

onMounted(async () => {

  canvas = document.getElementById('renderCanvas');
  engine = new BABYLON.Engine(canvas, true);
  scene = new BABYLON.Scene(engine);
  // 显示调试层
  await scene.debugLayer.show({
    embedMode: true,
  });


  const runRenderLoop = () => {
    engine.runRenderLoop(() => {
      scene.render();
    });
  };

  runRenderLoop();

  onUnmounted(() => {
    engine.dispose();
  });
  //-----------------------------------start------------------------------------------------
  xiangji();
  addlight()
  const { meshes } = await BABYLON.SceneLoader.ImportMeshAsync(
      null,          // 导入所有网格（不传特定网格名称）
      "",            // 模型路径（留空表示当前路径）
      "scene_xad.glb",    // 模型文件名
      scene
  );


  await path3D()

  //
  await chebyQxzou()


});

function setVisible(model, isVisible) {
  model.isVisible = isVisible;
  model.isPickable = isVisible;
  model.getChildMeshes().map(child => {
    child.isVisible = isVisible;
    child.isPickable = isVisible;
  })
}

async function createXADTrainModel(scene) {
  const group = new BABYLON.TransformNode('trainModelGroup');

  const models = [
    {name: 'GModel', filename: 'xad_gc.glb', errorMsg: '加载罐车模型异常'},
    {name: 'NModel', filename: 'xad_nx.glb', errorMsg: '加载平车模型异常'},
    {name: 'PModel', filename: 'xad_pc.glb', errorMsg: '加载棚车模型异常'}
  ];

  for (const modelInfo of models) {
    try {
      const result = await BABYLON.SceneLoader.ImportMeshAsync(null, '/model/train/', modelInfo.filename, scene);
      const model = result.meshes[0];
      model.name = modelInfo.name;
      model.position = new BABYLON.Vector3(0, 0.12, 0);// (debugNode as BABYLON.Mesh)
      setVisible(model, false);
      model.parent = group;
    } catch (error) {
      console.error(modelInfo.errorMsg, error);
    }
  }
  return group;
}




const start = async () => {
  // const container = await BABYLON.LoadAssetContainerAsync("scene_xad.glb", scene);
  const container = await BABYLON.AppendSceneAsync("scene_xad.glb", scene);
  //加载场景
  // const container2 = await BABYLON.AppendSceneAsync("lujing01.glb", scene);

  const trainModelGroup = await createXADTrainModel(scene);
  //创建模型
  //添加平行光

  // 阴影
  // shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
  // shadowGenerator.useBlurExponentialShadowMap = true;

  var meshByName = scene.getMeshByName('GModel');

  //
  // var meshByName2 = scene.getMeshByName('Curve001');
  // console.log('Curve001', meshByName2)
  // const positions = meshByName2.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  // console.log(positions)
  // const path = []
  // for (let i = 0; i < positions.length; i += 3) {
  //   const x = positions[i];
  //   const y = positions[i + 2];
  //   const z = positions[i + 1];
  //   path.push(new BABYLON.Vector3(x, y, z));
  // }
  //
  // var path3D = new BABYLON.Path3D(path);
  // const pathLines = BABYLON.MeshBuilder.CreateLines("pathLines", {points: path3D.getPoints()}, scene);
  // pathLines.color = new BABYLON.Color3(1, 0, 0); // 设置为红色


  // // 定义间距
  // const spacing = 5; // 可以根据需要调整间距
  // let index = 0;
  // while (index < 3) {
  //   const point = path3D.getPoints()[index];
  //   console.log(point)
  //   // 克隆一个车模型
  //   const clonedTrain = meshByName.clone(`clonedTrain_${index}`);
  //   clonedTrain.position = point;
  //
  //   // 计算切线向量
  //   const tangents = path3D.getTangents();
  //   const tangent = tangents[index].normalize();
  //   clonedTrain.rotation.y = Math.atan2(tangent.x, tangent.z);
  //   index += spacing;
  // }
  const clonedTrain = meshByName.clone(`clonedTrain_1`);

  clonedTrain.position = new BABYLON.Vector3(43.5067024230957, 0.12, -20.122920989990234)




}

const xianduan=()=>{
  //1.简单线段
// 定义线段的点集合（至少两个点）
  const points = [
    new BABYLON.Vector3(-2, 0, 0), // 起点
    new BABYLON.Vector3(0, 2, 0),  // 中间点
    new BABYLON.Vector3(2, 0, 0)   // 终点
  ];

// 创建线段
  const lines = BABYLON.MeshBuilder.CreateLines("lines", {
    points: points,
    updatable: false // 是否可更新（影响性能）
  }, scene);


}

</script>

<style scoped>
#renderCanvas {
  width: 100%;
  height: 100vh;
}
</style>